<template>
  <div ref="chartContainer" class="d3-chart 1111"></div>

  <!-- 家族成员表单弹窗 -->
  <el-drawer
    v-model="dialog.visible"
    :title="dialog.title"
    :size="drawerSize"
    @close="handleCloseDialog"
  >
    <el-form ref="dataFormRef" :model="formData" :rules="rules" label-width="100px">
      <el-form-item label="姓" prop="firstName">
        <el-input v-model="formData.firstName" placeholder="姓" />
      </el-form-item>

      <el-form-item label="名" prop="lastName">
        <el-input v-model="formData.lastName" placeholder="名" />
      </el-form-item>

      <el-form-item label="性别" prop="gender">
        <el-radio-group v-model="formData.gender">
          <el-radio :label="1">男</el-radio>
          <el-radio :label="2">女</el-radio>
        </el-radio-group>
      </el-form-item>

      <el-form-item label="是否在世" prop="isAlive">
        <el-radio-group v-model="formData.isAlive">
          <el-radio :label="true">在世</el-radio>
          <el-radio :label="false">已故</el-radio>
        </el-radio-group>
      </el-form-item>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="handleSubmit">确定</el-button>
        <el-button @click="handleCloseDialog()">取消</el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed, reactive } from "vue";
import * as d3 from "d3";
import { useAppStore } from "@/store";
import { DeviceEnum } from "@/enums/index.js";

const props = defineProps({
  modelValue: Object,
  treeList: Array,
  currentUserId: String,
  title: String
});

const emit = defineEmits([
  'update:modelValue',
  'node-click'
]);

const appStore = useAppStore();
const drawerSize = computed(() => (appStore.device === DeviceEnum.DESKTOP ? "500px" : "90%"));
const chartContainer = ref(null);
let svg;
let zoom;
let menu;
let currentTransform = null;

// 弹窗相关
const dialog = reactive({
  title: "新增成员",
  visible: false,
  type: 0 // 0: 编辑, 1: 新增父辈, 2: 新增配偶, 3: 新增子辈
});

const dataFormRef = ref();

// 初始表单数据
const initialFormData = {
  id: undefined,
  firstName: "",
  lastName: "",
  gender: 1,
  isAlive: true,
  parentId: undefined,
  children: [],
  spouseList: []
};

// 表单数据
const formData = ref({ ...initialFormData });

// 表单校验规则
const rules = reactive({
  firstName: [{ required: true, message: "请输入姓", trigger: "blur" }],
  lastName: [{ required: true, message: "请输入名", trigger: "blur" }],
  gender: [{ required: true, message: "请选择性别", trigger: "change" }],
  isAlive: [{ required: true, message: "请选择是否在世", trigger: "change" }]
});

// 创建全局右键菜单容器
function createContextMenu() {
  menu = d3.select("body")
    .append("div")
    .attr("id", "d3-context-menu")
    .style("position", "fixed")
    .style("z-index", 9999)
    .style("display", "none");
}

// 渲染家谱树
function renderTree(data) {
  if (!chartContainer.value) return;

  // 清除之前的内容
  d3.select(chartContainer.value).selectAll("*").remove();

  // 将单一树转换为树列表
  const treeList = Array.isArray(data) ? data : [data];

  // 如果列表为空或第一个元素没有firstName，则返回
  if (treeList.length === 0 || !treeList[0].firstName) return;

  const width = 1200;
  const height = 800;

  // 节点尺寸和间距
  const nodeWidth = 120;
  const nodeHeight = 80;
  const baseSpouseSpacing = 200; // 基础配偶间距
  const levelSpacing = 200; // 层级间距
  const baseSiblingSpacing = 150; // 基础兄弟节点间距

  // 创建SVG容器
  svg = d3.select(chartContainer.value)
    .append("svg")
    .attr("width", "100%")
    .attr("height", "100%")
    .attr("viewBox", `0 0 ${width} ${height}`)
    .style("background-color", "#f5f5f5");

  const g = svg.append("g");

  // 添加标题
  svg.append("text")
    .attr("x", width / 2)
    .attr("y", 30)
    .attr("text-anchor", "middle")
    .attr("font-size", "20px")
    .attr("font-weight", "bold")
    .text(props.title || "家族谱系图");

  // 添加缩放功能
  zoom = d3.zoom()
    .scaleExtent([0.1, 2])
    .on("zoom", (event) => {
      g.attr("transform", event.transform);
      currentTransform = event.transform;
    });

  svg.call(zoom);

  // 初始缩放
  const initialScale = 0.7;
  const initialTransform = d3.zoomIdentity.scale(initialScale).translate(width * 0.2, height * 0.2);

  if (currentTransform) {
    svg.call(zoom.transform, currentTransform);
  } else {
    svg.call(zoom.transform, initialTransform);
    currentTransform = initialTransform;
  }

  // 为每棵树创建布局
  treeList.forEach((treeData, treeIndex) => {
    // 预先计算每个节点的配偶数量，用于后续间距调整
    function calculateSpouses(node) {
      node.spouseCount = node.spouseList ? node.spouseList.length : 0;
      if (node.children && node.children.length > 0) {
        node.children.forEach(calculateSpouses);
      }
      return node;
    }

    // 计算每个节点的子节点数量，用于调整兄弟节点间距
    function calculateChildrenCount(node) {
      if (!node.children || node.children.length === 0) {
        node.totalChildrenCount = 0;
        return 0;
      }

      let totalCount = 0;
      node.children.forEach(child => {
        totalCount += calculateChildrenCount(child) + 1;
      });

      node.totalChildrenCount = totalCount;
      return totalCount;
    }

    // 应用计算
    calculateSpouses(treeData);
    calculateChildrenCount(treeData);

    // 创建树布局
    const treeLayout = d3.tree()
      .size([width * 0.8, height - 120])
      .nodeSize([baseSiblingSpacing, levelSpacing])
      .separation((a, b) => {
        // 动态计算节点间距
        const aSpouses = a.data.spouseCount || 0;
        const bSpouses = b.data.spouseCount || 0;

        // 基础间距系数
        let baseSeparation = a.parent === b.parent ? 1.5 : 2;

        // 根据配偶数量增加间距
        let spouseAdjustment = (aSpouses + bSpouses) * 0.8;

        // 根据子节点数量增加间距
        const aChildren = a.data.totalChildrenCount || 0;
        const bChildren = b.data.totalChildrenCount || 0;
        let childrenAdjustment = Math.max(aChildren, bChildren) * 0.3;

        return baseSeparation + spouseAdjustment + childrenAdjustment;
      });

    const root = d3.hierarchy(treeData);
    treeLayout(root);

    // 创建每棵树的容器
    const treeG = g.append("g")
      .attr("class", `tree-${treeIndex}`)
      .attr("transform", `translate(${treeIndex * (width * 0.8 + 100)}, 0)`);

    // 计算树的整体宽度，用于居中显示
    const xOffset = 100;
    const yOffset = 100;

    // 绘制连接线
    treeG.selectAll(".link")
      .data(root.links())
      .enter()
      .append("path")
      .attr("class", "link")
      .attr("d", d => {
        const sourceX = d.source.x + xOffset;
        const sourceY = d.source.y + yOffset;
        const targetX = d.target.x + xOffset;
        const targetY = d.target.y + yOffset;

        return `M${sourceX},${sourceY} L${sourceX},${(sourceY + targetY) / 2} L${targetX},${(sourceY + targetY) / 2} L${targetX},${targetY}`;
      })
      .attr("fill", "none")
      .attr("stroke", "#999")
      .attr("stroke-width", 1.5);

    // 预先创建夫妻连接线
    root.descendants().forEach(d => {
      if (d.data.spouseList && d.data.spouseList.length > 0) {
        const spouses = d.data.spouseList;
        const nodeX = d.x + xOffset;
        const nodeY = d.y + yOffset;

        // 动态计算配偶间距
        const spouseCount = spouses.length;
        // 如果配偶数量多，适当减小间距
        const adjustedSpacing = spouseCount > 1
          ? baseSpouseSpacing * (1 - 0.1 * (spouseCount - 1))
          : baseSpouseSpacing;

        spouses.forEach((spouse, i) => {
          treeG.append("line")
            .attr("class", "spouse-link")
            .attr("x1", nodeX)
            .attr("y1", nodeY)
            .attr("x2", nodeX + (i + 1) * adjustedSpacing)
            .attr("y2", nodeY)
            .attr("stroke", "#999")
            .attr("stroke-width", 1.5)
            .attr("stroke-dasharray", "3,3");
        });
      }
    });

    // 添加节点
    const nodes = treeG.selectAll(".node")
      .data(root.descendants())
      .enter()
      .append("g")
      .attr("class", "node")
      .attr("transform", d => `translate(${d.x + xOffset},${d.y + yOffset})`)
      .on("contextmenu", (event, d) => {
        event.preventDefault();
        showContextMenu(event, d);
      });

    // 节点矩形
    nodes.append("rect")
      .attr("width", nodeWidth)
      .attr("height", nodeHeight)
      .attr("x", -nodeWidth/2)
      .attr("y", -nodeHeight/2)
      .attr("rx", 5)
      .attr("data-user-id", d => d.data.id)
      .attr("fill", d => d.data.gender === 1 ? "#e6f2ff" : "#fff0f5")
      .attr("stroke", d => {
        // 为已故成员添加灰色边框
        if (d.data.isAlive === false) {
          return "#808080";
        }
        return d.data.gender === 1 ? "#4169E1" : "#C71585";
      })
      .attr("stroke-width", d => d.data.id === props.currentUserId ? 3 : 1.5)
      .attr("opacity", d => d.data.isAlive === false ? 0.7 : 1) // 已故成员透明度降低
      .on("click", (event, d) => {
        event.stopPropagation();
        showContextMenu(event, d);
      });

    // 节点姓名文字
    nodes.append("text")
      .text(d => `${d.data.firstName}${d.data.lastName}`)
      .attr("text-anchor", "middle")
      .attr("x", 0)
      .attr("y", 0)
      .attr("dy", "0.3em")
      .style("font-size", "14px")
      .style("font-weight", "bold")
      .style("pointer-events", "none");

    // 节点性别文字
    nodes.append("text")
      .text(d => d.data.gender === 1 ? "男" : "女")
      .attr("text-anchor", "middle")
      .attr("x", 0)
      .attr("y", 15)
      .attr("dy", "0.3em")
      .style("font-size", "12px")
      .style("pointer-events", "none");

    // 绘制配偶节点
    nodes.each(function(d) {
      const node = d3.select(this);
      const spouses = d.data.spouseList || [];

      // 动态计算配偶间距
      const spouseCount = spouses.length;
      // 如果配偶数量多，适当减小间距
      const adjustedSpacing = spouseCount > 1
        ? baseSpouseSpacing * (1 - 0.1 * (spouseCount - 1))
        : baseSpouseSpacing;

      spouses.forEach((spouse, i) => {
        const spouseGroup = node.append("g")
          .attr("class", "spouse-node")
          .attr("transform", `translate(${(i + 1) * adjustedSpacing},0)`);

        spouseGroup.append("rect")
          .attr("width", nodeWidth)
          .attr("height", nodeHeight)
          .attr("x", -nodeWidth/2)
          .attr("y", -nodeHeight/2)
          .attr("rx", 5)
          .attr("fill", spouse.gender === 1 ? "#e6f2ff" : "#fff0f5")
          .attr("stroke", spouse.isAlive === false ? "#808080" : (spouse.gender === 1 ? "#4169E1" : "#C71585"))
          .attr("stroke-width", 1.5)
          .attr("opacity", spouse.isAlive === false ? 0.7 : 1)
          .on("click", (event) => {
            const spouseNode = {
              ...spouse,
              parentId: d.data.id
            };
            const spouseHierarchyNode = {
              data: spouseNode,
              depth: d.depth,
              height: d.height,
              parent: d,
              children: []
            };
            showContextMenu(event, spouseHierarchyNode);
          });

        // 配偶姓名
        spouseGroup.append("text")
          .text(`${spouse.firstName}${spouse.lastName}`)
          .attr("text-anchor", "middle")
          .attr("x", 0)
          .attr("y", 0)
          .attr("dy", "0.3em")
          .style("font-size", "14px")
          .style("font-weight", "bold")
          .style("pointer-events", "none");

        // 配偶性别
        spouseGroup.append("text")
          .text(spouse.gender === 1 ? "男" : "女")
          .attr("text-anchor", "middle")
          .attr("x", 0)
          .attr("y", 15)
          .attr("dy", "0.3em")
          .style("font-size", "12px")
          .style("pointer-events", "none");
      });
    });
  });
}

// 显示右键菜单
function showContextMenu(event, d) {
  event.preventDefault();
  event.stopPropagation();

  const [x, y] = [event.pageX, event.pageY];

  // 判断是否为配偶节点
  const isSpouse = d.parent &&
    d.parent.data &&
    d.parent.data.spouseList &&
    d.parent.data.spouseList.some(sp => sp.id === d.data.id);

  // 检查是否已有父节点
  const hasParent = d.parent !== null;

  // 判断是否为叶子节点
  const isLeaf = !d.data.children || d.data.children.length === 0;
  const isSelf = d.data.id === props.currentUserId;

  let menuItems;
  if (isSpouse) {
    menuItems = [
      { action: "edit", label: "编辑" },
    ];
    if (!isSelf) {
      menuItems.push({ action: "delete", label: "删除" });
    }
  } else if (hasParent) {
    menuItems = [
      { action: "edit", label: "编辑" },
      { action: "add-child", label: "新增子辈" },
      { action: "add-spouse", label: "新增配偶" }
    ];
    if (isLeaf && !isSelf) {
      menuItems.push({ action: "delete", label: "删除" });
    }
  } else {
    menuItems = [
      { action: "edit", label: "编辑" },
      { action: "add-parent", label: "新增父辈" },
      { action: "add-child", label: "新增子辈" },
      { action: "add-spouse", label: "新增配偶" }
    ];
    if (isLeaf && !isSelf) {
      menuItems.push({ action: "delete", label: "删除" });
    }
  }

  menu.html(menuItems.map(item =>
    `<div class="menu-item" data-action="${item.action}">${item.label}</div>`
  ).join(""))
    .style("left", `${x + 10}px`)
    .style("top", `${y + 10}px`)
    .style("display", "block");

  menu.selectAll(".menu-item")
    .on("click", (event) => {
      event.stopPropagation();
      const action = d3.select(event.target).attr("data-action");
      handleMenuAction(action, d, isSpouse);
      menu.style("display", "none");
    });
}

// 处理菜单操作
function handleMenuAction(action, nodeData, isSpouse = false) {
  const actionMap = {
    "edit": 0,      // 编辑
    "add-parent": 1,  // 添加父辈
    "add-spouse": 2,   // 添加配偶
    "add-child": 3,   // 添加子辈
    "delete": 4,      // 删除
  };

  const type = actionMap[action];

  // 删除操作单独处理
  if (type === 4) {
    handleDeleteNode(nodeData, isSpouse);
    return;
  }

  // 打开弹窗
  dialog.visible = true;
  dialog.type = type;

  // 根据不同类型设置不同的标题和数据
  if (type === 0) {
    dialog.title = "编辑成员信息";
    formData.value = { ...nodeData.data };
  } else if (type === 1) {
    dialog.title = "新增父辈成员信息";
    // 深拷贝原节点数据，并清空配偶
    const childNode = { ...nodeData.data, spouseList: [] };
    formData.value = { ...initialFormData, children: [childNode] };
  } else if (type === 2) {
    dialog.title = "新增配偶成员信息";
    formData.value = {
      ...initialFormData,
      gender: nodeData.data.gender === 1 ? 2 : 1,
      parentId: nodeData.data.id
    };
  } else if (type === 3) {
    dialog.title = "新增子辈成员信息";
    formData.value = { ...initialFormData, parentId: nodeData.data.id };
  }
}

// 删除节点或配偶
function handleDeleteNode(nodeData, isSpouse) {
  let updatedTree = null;
  if (isSpouse) {
    // 删除配偶
    updatedTree = removeSpouseById(props.modelValue, nodeData.data.id);
  } else {
    // 删除成员（叶子节点）
    updatedTree = removeNodeById(props.modelValue, nodeData.data.id);
  }
  if (updatedTree) {
    emit('update:modelValue', updatedTree);
    renderTree(updatedTree);
  }
}

// 移除成员节点（只会移除叶子节点）
function removeNodeById(tree, id) {
  if (!tree) return null;
  // 不能删除根节点
  if (tree.id === id) return tree;
  let updatedTree = { ...tree };
  if (tree.children && tree.children.length > 0) {
    updatedTree.children = tree.children
      .filter(child => child.id !== id)
      .map(child => removeNodeById(child, id));
  }
  // 配偶列表递归不处理成员删除
  return updatedTree;
}

// 移除配偶节点
function removeSpouseById(tree, spouseId) {
  if (!tree) return null;
  let updatedTree = { ...tree };
  if (tree.spouseList && tree.spouseList.length > 0) {
    updatedTree.spouseList = tree.spouseList.filter(spouse => spouse.id !== spouseId);
  }
  if (tree.children && tree.children.length > 0) {
    updatedTree.children = tree.children.map(child => removeSpouseById(child, spouseId));
  }
  return updatedTree;
}

// 提交表单
function handleSubmit() {
  dataFormRef.value.validate((valid) => {
    if (valid) {
      let updatedTree = null;

      if (dialog.type === 0) {
        // 编辑节点
        updatedTree = updateNodeInTree(props.modelValue, formData.value);
      } else if (dialog.type === 1) {
        // 添加父辈
        updatedTree = {
          ...formData.value,
          id: Date.now().toString(),
          children: [props.modelValue]
        };
      } else if (dialog.type === 2) {
        // 添加配偶
        const currentNode = findNodeById(props.modelValue, formData.value.parentId);
        if (currentNode) {
          if (!currentNode.spouseList) {
            currentNode.spouseList = [];
          }

          // 创建新配偶对象，只包含必要信息，不包含子节点关系
          const newSpouse = {
            id: Date.now().toString(),
            firstName: formData.value.firstName,
            lastName: formData.value.lastName,
            gender: formData.value.gender,
            isAlive: formData.value.isAlive
          };

          currentNode.spouseList.push(newSpouse);
          updatedTree = { ...props.modelValue };
        }
      } else if (dialog.type === 3) {
        // 添加子辈
        const parentNode = findNodeById(props.modelValue, formData.value.parentId);
        if (parentNode) {
          if (!parentNode.children) {
            parentNode.children = [];
          }
          parentNode.children.push({
            id: Date.now().toString(),
            firstName: formData.value.firstName,
            lastName: formData.value.lastName,
            gender: formData.value.gender,
            isAlive: formData.value.isAlive,
            parentId: formData.value.parentId
          });
          updatedTree = { ...props.modelValue };
        }
      }

      if (updatedTree) {
        emit('update:modelValue', updatedTree);
        emit('node-click', formData.value, dialog.type);
        renderTree(updatedTree);
      }

      handleCloseDialog();
    }
  });
}

// 在树中查找节点
function findNodeById(tree, id) {
  if (!tree || !id) return null;

  if (tree.id === id) {
    return tree;
  }

  // 检查子节点
  if (tree.children && tree.children.length > 0) {
    for (const child of tree.children) {
      const found = findNodeById(child, id);
      if (found) return found;
    }
  }

  // 检查配偶列表
  if (tree.spouseList && tree.spouseList.length > 0) {
    for (const spouse of tree.spouseList) {
      if (spouse.id === id) {
        return spouse;
      }
    }
  }

  return null;
}

// 在树中更新节点
function updateNodeInTree(tree, node) {
  if (!tree) return null;

  if (tree.id === node.id) {
    return { ...tree, ...node };
  }

  let updatedTree = { ...tree };

  // 检查子节点
  if (tree.children && tree.children.length > 0) {
    updatedTree.children = tree.children.map(child => updateNodeInTree(child, node));
  }

  // 检查配偶列表
  if (tree.spouseList && tree.spouseList.length > 0) {
    updatedTree.spouseList = tree.spouseList.map(spouse =>
      spouse.id === node.id ? { ...spouse, ...node } : spouse
    );
  }

  return updatedTree;
}

// 关闭弹窗
function handleCloseDialog() {
  dialog.visible = false;
  dataFormRef.value?.resetFields();
  formData.value = { ...initialFormData };
}

// 监听数据变化
watch(() => [props.modelValue, props.treeList], ([newModelValue, newTreeList]) => {
  if (newTreeList && newTreeList.length > 0) {
    renderTree(newTreeList);
  } else if (newModelValue) {
    renderTree(newModelValue);
  }
}, { deep: true });

// 组件挂载时初始化
onMounted(() => {
  createContextMenu();
  if (props.treeList && props.treeList.length > 0) {
    renderTree(props.treeList);
  } else if (props.modelValue) {
    renderTree(props.modelValue);
  }

  // 添加点击事件监听器来关闭菜单
  d3.select("body").on("click.context-menu", () => {
    if (menu) {
      menu.style("display", "none");
    }
  });
});

// 组件卸载前清理
onBeforeUnmount(() => {
  if (menu) {
    menu.remove();
  }
  if (svg) {
    svg.selectAll("*").remove();
  }
  d3.select("body").on("click.context-menu", null);
});

// 导出方法
defineExpose({
  renderTree
});
</script>

<style scoped>
.d3-chart {
  width: 100%;
  height: 100%;
  min-height: 500px;
  position: relative;
  background-color: #f5f5f5;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}
</style>

<style>
#d3-context-menu {
  background: white;
  border-radius: 4px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
  padding: 8px 0;
  min-width: 120px;
  z-index: 9999;
}

#d3-context-menu .menu-item {
  padding: 8px 16px;
  color: #333;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.2s;
}

#d3-context-menu .menu-item:hover {
  background: #f5f5f5;
  color: #409EFF;
}
</style>
